import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * 
 * @author kathryn.a.baldwin
 *
 */
public class VendingMachineTest {
	/**
	 * Vending machines and vending machine items
	 * for use in the functions
	 */
	VendingMachine m;
	VendingMachineItem sprite, twix, snickers,cookies, gummies, pretzels,
	snowcaps,nerds;
	
	/**
	 * A new vending machine is created for use in the 
	 * functions
	 */
	@Before
	public void setUp() throws Exception {
		m = new VendingMachine();
		
	}

	@After
	public void tearDown() throws Exception {
		
	}

	/**
	 * Test to see that when a vending machine item is added to a 
	 * vending machine in a particular slot, that it is correctly stored
	 * in that slot (which is designated by its code).
	 */
	@Test
	public void testAddItem() {
	
		
		sprite = new VendingMachineItem("Sprite",1.5);
		m.addItem(sprite, "A");
		assertTrue(m.getItem("A") == sprite);
		twix = new VendingMachineItem("Twix",.75);
		m.addItem(twix,m.B_CODE);
		assertTrue(m.getItem(m.B_CODE)== twix);
	}
	
	/**
	 *testAddItems2
	 *This test attempts to put two items in the same slot,
	 *and should throw an error if working correctly. It 
	 *should not allow two items to be put in the same slot. 
	 */
	@Test
	public void testAddItem2()
	{
		
		snickers = new VendingMachineItem("snickers",.50);
		cookies = new VendingMachineItem("cookies",.80);
		m.addItem(cookies, "A");
		m.addItem(snickers,m.A_CODE);
		
		
	}
	
	/**
	 * testRemoveItem
	 * This test should show that an item 
	 * can be removed from the vending machine,
	 * thus causing the slot to become empty once
	 * more
	 */
	@Test
	public void testRemoveItem() {
		
		gummies = new VendingMachineItem("gummies",.50);
		//Boolean t = true;
		m.addItem(gummies,"B");
		
		System.out.println("Slot B contains:"+ m.getItem("B"));
		m.insertMoney(1);
		m.makePurchase("B");
		//m.removeItem("B");
		//assertEquals(("B".isEmpty()), true);
		//assertTrue(m.B_CODE.isEmpty());
		System.out.println("The B Slot is empty, yes?"+m.getItem("B"));
		m.addItem(gummies, "B");
		System.out.println("The B Slot is empty, yes?"+m.getItem("B"));
		m.makePurchase("B");
		System.out.println("The B Slot is empty, yes?"+m.getItem("B"));
	}
	
	/**
	 * testRemoveItem2
	 * Test that uses an invalid code when trying to remove 
	 * an item from the vending machine. This should produce an 
	 * error.
	 */
	@Test
	public void testRemoveItem2()
	{
	
		gummies = new VendingMachineItem("gummies",2.0);
		m.addItem(gummies, "C");
	
		m.removeItem("H");
		
	}
	
	/**
	 * testRemoveItem3
	 * This test tries to remove an item from an empty slot
	 * in the vending machine. This should throw an exception,
	 * this should not be possible. 
	 */
	@Test
	public void testRemoveItem3()
	{
		
		snickers = new VendingMachineItem("snickers",1.0);
		m.addItem(snickers, "A");
		
		m.removeItem("B");
		
		
	}
	
	/**
	 * testInsertMoney
	 * Test that checks to make sure money is inserted
	 * into the vending machine correctly. 
	 */
 
	@Test
	public void testInsertMoney() {
		double balance = 0;
		
		m.insertMoney(2.0);
		balance = balance + m.getBalance();
		assertEquals(2.0,balance,0);
		
	}
	
	/**
	 * testInsertMoney2
	 * This test tries to put in 0 money into
	 * the vending machine and checks to see that 
	 * it was inserted correctly. 
	 */
	@Test
	public void testInsertMoney2()
	{
		double balance = 0;
	
		m.insertMoney(0);
		balance = balance + m.getBalance();
		assertEquals(0,balance,0);
		
	}
	
	/**
	 * testInsertMoney3
	 * This test checks to see if an exception is correctly
	 * thrown when trying to input a negative amount into the 
	 * vending machine. 
	 */
	@Test
	public void testInsertMoney3()
	{
		double balance = 0;
		
		m.insertMoney(-2);
		balance = balance + m.getBalance();
		
		
	}
	
	/**
	 * testInsertMoney4
	 * This test adds money and then inputs a negative amount
	 * greater than the money added. This should produce an 
	 * error. 
	 */
	@Test
	public void testInsertMoney4()
	{
		double balance = 0;
		m.insertMoney(3);
		m.insertMoney(-4);
		balance = balance + m.getBalance();
		
	}
	
	/**
	 * testInsertMoney5
	 * This test adds money and to the vending machine
	 * and then tries to make a purchase for an item
	 * of greater value than the money put in. This should
	 * not be possible
	 */
	@Test
	public void testInsertMoney5()
	{
		double balance = 0;
		
		cookies = new VendingMachineItem("cookies",5.0);
		m.insertMoney(3);
		m.addItem(cookies,"A");
		m.makePurchase("A");
		//balance = balance + m.getBalance();
		
		
	}
	
	/**
	 * testInsertMoney6
	 * This test checks to see if you can insert money 
	 * into the vending machine that would not be a real
	 * currently value (1.2222). This should not be
	 * possible. 
	 */
	@Test
	public void testInsertMoney6()
	{
		
		m.insertMoney(10);
		m.insertMoney(1.2222);
		m.returnChange();
		
	}
	
	/**
	 * testGetBalance
	 * This test should check to see that the 
	 * getBalance() function is working correctly.
	 * After money is inserted, it should correctly 
	 * return the amount of money currently in the 
	 * vending machine. 
	 */
	@Test
	public void testGetBalance() {
		
		m.insertMoney(5);
		assertEquals(5,m.getBalance(),0);
	}
	/**
	 * testGetBalance2
	 * This test checks to see that the starting
	 * balance of the vending machine is 0
	 */
	@Test
	public void testGetBalance2(){
		assertEquals(0,m.getBalance(),0);
	}
	/**
	 * testGetBalance3
	 * This test checks to see what getBalance()
	 * returns if an attempt is made to purchase 
	 * something worth more than the money in the 
	 * vending machine, will it have a negative value?
	 * It should instead not allow the purchase to be made.
	 */
	@Test
	public void testGetBalance3(){
		m.insertMoney(4);
		snowcaps = new VendingMachineItem("snowcaps",6);
		m.addItem(snowcaps, "A");
		m.makePurchase("A");
		System.out.println("Balance: "+m.getBalance());
		
	}
	/**
	 * testMakePurchase
	 * This test checks to see that an item can be 
	 * purchased that is in the vending machine 
	 */
	@Test
	public void testMakePurchase() {
		pretzels = new VendingMachineItem("pretzels",2);
		m.addItem(pretzels, "A");
		m.makePurchase("A");
	}
	/**
	 *testMakePurchase2
	 *This test should attempt to make a purchase even
	 *though no items have been placed in the vending 
	 *machine. This should not be allowed. 	 
	 */
	@Test
	public void testMakePurchase2(){
		pretzels = new VendingMachineItem("pretzels",2);
		m.makePurchase("A");
	}
	/**
	 * testMakePurchase3
	 * This test checks to see if a purchase can be made
	 * for an empty slot. This should not be allowed according
	 * to the comments for this makePurchase() function.
	 */
	@Test
	public void testMakePurchase3(){
		pretzels = new VendingMachineItem("pretzels",2);
		m.addItem(pretzels,"A");
		System.out.println("Anything in slot B?"+m.getItem("B"));
		m.makePurchase("B");
	}
	/**
	 * testReturnChange
	 * This test has a user enter money, then make a purchase
	 * for the item in slot A (which is less than the amount
	 * of money they put in. 
	 */
	@Test
	public void testReturnChange() {
		
	
		cookies = new VendingMachineItem("cookies",3.0);
		m.addItem(cookies,"A");
		m.insertMoney(6);
		System.out.println("Current balance:"+m.balance);
		m.makePurchase("A");
		
		m.returnChange();
		System.out.println("Balance after returning " +
				"change"+m.balance);
		assertTrue(m.balance>= 0);
		m.insertMoney(12);
		System.out.println("Current balance:"+m.balance);
		m.makePurchase("A");
		m.returnChange();
		System.out.println("Current balance after returning" +
				"change:"+m.balance);
		
	}
	/**
	 * testReturnChange2
	 * This test checks to see if change is returned when
	 * the exact amount of money is in the vending machine
	 * for the item selected for purchase. 
	 */
	@Test
	public void testReturnChange2(){
		nerds = new VendingMachineItem("nerds",1);
		m.addItem(nerds, "A");
		m.insertMoney(1);
		System.out.println("Current balance:"+m.balance);
		m.makePurchase("A");
		m.returnChange();
		System.out.println("Current balance:"+m.balance);
	}
	
	/**
	 * testReturnChange3
	 * This test tries to begin with a negative balance, 
	 * then adds money to give it a positive balance.
	 * Then tries to return the change. It should not be
	 * able to start with a negative balance, according
	 * to the comments for returnChange()
	 */
	@Test
	public void testReturnChange3(){
		m.balance = -2;
		m.insertMoney(4);
		System.out.println("Current balance:"+m.balance);
		m.returnChange();
		System.out.println("Current balance after returning change:"+m.balance);
	}

}
